package com.zzyl.intercept;

import com.zzyl.enums.BasicEnum;
import com.zzyl.properties.JwtTokenManagerProperties;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.UserThreadLocal;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description AdminTokenInterceptor
 * @Author loe
 * @Date 2024-07-21
 */

@Component
public class AdminTokenInterceptor implements HandlerInterceptor {
    /**
     * JWT令牌管理器的属性配置。
     */
    @Autowired
    private JwtTokenManagerProperties jwtTokenManagerProperties;

    /**
     * 在请求处理之前执行，用于验证JWT令牌并设置当前用户信息。
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  将要处理的请求的处理器对象
     * @return 是否继续处理该请求
     * @throws Exception 如果验证失败抛出异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果处理器不是HandlerMethod实例，直接返回true，不进行后续处理
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // 从请求头中获取JWT令牌
        String token = request.getHeader("Authorization");
        // 如果令牌不存在，抛出异常，提示登录失败
        if (token == null) {
            throw new RuntimeException(BasicEnum.LOGIN_FAIL.msg);
        }
        // 使用JWT工具类和秘钥解析JWT令牌
        Claims claims = JwtUtil.parseJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), token);
        // 从令牌中获取当前用户信息，并设置到线程安全的ThreadLocal中，以便后续使用
        String json = claims.get("currentUser").toString();
        UserThreadLocal.setSubject(json);
        return true;
    }

    /**
     * 请求处理完成后执行，用于清除线程安全的ThreadLocal中的当前用户信息。
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  处理请求的处理器对象
     * @param ex       在处理过程中抛出的异常
     * @throws Exception 如果清除失败抛出异常
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 清除线程安全的ThreadLocal中的当前用户信息
        UserThreadLocal.removeSubject();
    }
}
